﻿using chatGUI.Model;
using GalaSoft.MvvmLight;
using System.Collections.ObjectModel;
using System;
using HandyControl.Data;
using System.Windows;
using GalaSoft.MvvmLight.Command;
using HandyControl.Controls;
using HandyControl.Tools;
using System.Media;
using System.Windows.Input;
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Win32;
using System.Security.Cryptography;
using System.Windows.Media.Imaging;
using System.IO;
using messageData;
using chatGUI.DataBase.Entity;
using System.Collections.Generic;
using chatGUI.SingeltonData;
using chatGUI.DataBase.Dao;
using System.Xml.Serialization;

namespace chatGUI.ViewModel
{
    class chatAndDetailViewModel : ViewModelBase
    {
        public chatAndDetailViewModel()
        {
            Id = "User" + userData.Instance.nowChattingWith.Substring(1);
            IsGroup = false;
            ChatStr = String.Empty;
            initChattingOppsite();
            ChatBubbleModels = new ObservableCollection<chatBubbleModel>(); 
            Messenger.Default.Register<CommunicateMessage>(this, "textMessage", recieveTextMessage);
            Messenger.Default.Register<CommunicateMessage>(this, "gifMessage", recieveGifMessage);
            Messenger.Default.Register<CommunicateMessage>(this, "imageMessage", recieveImageMessage);
            Messenger.Default.Register<CommunicateMessage>(this, "fileMessage", recieveFileMessage);
            Messenger.Default.Register<string>(this, "initChatMessageFormDataBase", initChatMessageFormDataBase);
        }
        private string id;
        public string Id
        {
            get => id;
            set => Set(ref id, value);
        }
        private string chatStr;
        public string ChatStr
        {
            get => chatStr;
            set => Set(ref chatStr, value);
        }
        private bool isGroup;
        public bool IsGroup
        {
            get => isGroup;
            set => Set(ref isGroup, value);
        }
        public Visibility IsDeleteFriendButton
        {
            get => isGroup ? Visibility.Collapsed : Visibility.Visible;
        }
        public Visibility IsGroupButton
        {
            get => isGroup ? Visibility.Visible : Visibility.Collapsed;
        }
        private userDataModel userDataModel;
        public userDataModel UserDataModel
        {
            get => userDataModel;
            set => Set(ref userDataModel, value);
        }
        private ObservableCollection<chatBubbleModel> chatBubbleModels;
        public ObservableCollection<chatBubbleModel> ChatBubbleModels
        {
            get => chatBubbleModels; 
            set => Set(ref chatBubbleModels, value);
        }

        public RelayCommand<RoutedEventArgs> OpenImageCmd => new Lazy<RelayCommand<RoutedEventArgs>>(() =>
            new RelayCommand<RoutedEventArgs>(OpenImg)).Value;
        private void OpenImg(RoutedEventArgs e)
        {
            if (e.OriginalSource is FrameworkElement element && element.Tag is chatBubbleModel info)
            {
                if (info.ChatBubbleType == chatBubbleType.picture)
                {
                    new ImageBrowser(new Uri(info.Message.ToString()))
                    {
                        Owner = WindowHelper.GetActiveWindow()
                    }.Show();
                }
            }
        }
        public RelayCommand<KeyEventArgs> SendStringCmd => new Lazy<RelayCommand<KeyEventArgs>>(() =>
            new RelayCommand<KeyEventArgs>(SendString)).Value;

        private void SendString(KeyEventArgs e){
            if (e.Key == Key.Enter) {
            }
        }

        public RelayCommand<RoutedEventArgs> SendStringButtonCmd => new Lazy<RelayCommand<RoutedEventArgs>>(() =>
            new RelayCommand<RoutedEventArgs>(SendStringButton)).Value;
        private void SendStringButton(RoutedEventArgs e)
        {
        }
        public RelayCommand<RoutedEventArgs> SendGifCmd => new Lazy<RelayCommand<RoutedEventArgs>>(() =>
            new RelayCommand<RoutedEventArgs>(SendGifButton)).Value;
        private void SendGifButton(RoutedEventArgs e)
        {
        }
        public RelayCommand<RoutedEventArgs> SendImageStr => new Lazy<RelayCommand<RoutedEventArgs>>(() =>
            new RelayCommand<RoutedEventArgs>(SendImageButton)).Value;
        private void SendImageButton(RoutedEventArgs e)
        {
        }
        public RelayCommand<RoutedEventArgs> SendFileStr => new Lazy<RelayCommand<RoutedEventArgs>>(() =>
            new RelayCommand<RoutedEventArgs>(SendFileButton)).Value;
        private void SendFileButton(RoutedEventArgs e)
        {
        }
        public RelayCommand<RoutedEventArgs> DeleteFriendCmd => new Lazy<RelayCommand<RoutedEventArgs>>(() =>
            new RelayCommand<RoutedEventArgs>(DeleteFriend)).Value;
        private void DeleteFriend(RoutedEventArgs e)
        {
            Messenger.Default.Send(userData.Instance.nowChattingWith, "deleteFriend");
        }
        public RelayCommand<RoutedEventArgs> WithdrawGroupCmd => new Lazy<RelayCommand<RoutedEventArgs>>(() =>
            new RelayCommand<RoutedEventArgs>(WithdrawGroup)).Value;
        private void WithdrawGroup(RoutedEventArgs e)
        {
            Messenger.Default.Send(userData.Instance.nowChattingWith, "withdrawGroup");
        }

        private void recieveTextMessage(CommunicateMessage communication_message)
        {
            System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
            {
                string gid = communication_message.sender;
                if (communication_message.sender.Contains(' '))
                {
                    gid = communication_message.sender.Substring(0, communication_message.sender.IndexOf(' '));
                    communication_message.sender = communication_message.sender.Substring(communication_message.sender.LastIndexOf(' ') + 1);
                }
                if(gid != userData.Instance.nowChattingWith)
                {
                    return;
                }
                var info = new chatBubbleModel
                {
                    SenderAvatarUrlStr = FriendDao.SelectById(userData.Instance.user.uid, communication_message.sender).AvatarUrl,
                    SenderNickName = FriendDao.SelectById(userData.Instance.user.uid, communication_message.sender).NickName,
                    SendTime = DateTime.Now,
                    ChatBubbleRole = chatBubbleRole.sender,
                    TimeVisiblity = isTimeVisible(),
                    ChatBubbleType = chatBubbleType.text,
                    Message = communication_message.Data[0]
                };
                ChatBubbleModels.Add(info);
            }));
        }
        private void recieveGifMessage(CommunicateMessage communication_message)
        {
            System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
            {
                string gid = communication_message.sender;
                if (communication_message.sender.Contains(' '))
                {
                    gid = communication_message.sender.Substring(0, communication_message.sender.IndexOf(' '));
                    communication_message.sender = communication_message.sender.Substring(communication_message.sender.LastIndexOf(' ') + 1);
                }
                if (gid != userData.Instance.nowChattingWith)
                {
                    return;
                }
                var info = new chatBubbleModel
                {
                    SenderAvatarUrlStr = FriendDao.SelectById(userData.Instance.user.uid, communication_message.sender).AvatarUrl,
                    SenderNickName = FriendDao.SelectById(userData.Instance.user.uid, communication_message.sender).NickName,
                    SendTime = DateTime.Now,
                    ChatBubbleRole = chatBubbleRole.sender,
                    TimeVisiblity = isTimeVisible(),
                    ChatBubbleType = chatBubbleType.gif,
                    Message = miniClientData.Instance.client.file_helper.path + @$"\Images\{(string)communication_message.Data[1]}"
                };
                ChatBubbleModels.Add(info);
            }));
        }
        private void recieveImageMessage(CommunicateMessage communication_message)
        {
            System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
            {
                string gid = communication_message.sender;
                if (communication_message.sender.Contains(' '))
                {
                    gid = communication_message.sender.Substring(0, communication_message.sender.IndexOf(' '));
                    communication_message.sender = communication_message.sender.Substring(communication_message.sender.LastIndexOf(' ') + 1);
                }
                if (gid != userData.Instance.nowChattingWith)
                {
                    return;
                }
                var info = new chatBubbleModel
                {
                    SenderAvatarUrlStr = FriendDao.SelectById(userData.Instance.user.uid, communication_message.sender).AvatarUrl,
                    SenderNickName = FriendDao.SelectById(userData.Instance.user.uid, communication_message.sender).NickName,
                    SendTime = DateTime.Now,
                    ChatBubbleRole = chatBubbleRole.sender,
                    TimeVisiblity = isTimeVisible(),
                    ChatBubbleType = chatBubbleType.picture,
                    Message = miniClientData.Instance.client.file_helper.path + @$"\Images\{(string)communication_message.Data[1]}"
                };
                ChatBubbleModels.Add(info);
            }));
        }
        private void recieveFileMessage(CommunicateMessage communication_message)
        {
            System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
            {
                string gid = communication_message.sender;
                if (communication_message.sender.Contains(' '))
                {
                    gid = communication_message.sender.Substring(0, communication_message.sender.IndexOf(' '));
                    communication_message.sender = communication_message.sender.Substring(communication_message.sender.LastIndexOf(' ') + 1);
                }
                if (gid != userData.Instance.nowChattingWith)
                {
                    return;
                }
                var info = new chatBubbleModel
                {
                    SenderAvatarUrlStr = FriendDao.SelectById(userData.Instance.user.uid, communication_message.sender).AvatarUrl,
                    SenderNickName = FriendDao.SelectById(userData.Instance.user.uid, communication_message.sender).NickName,
                    SendTime = DateTime.Now,
                    ChatBubbleRole = chatBubbleRole.sender,
                    TimeVisiblity = isTimeVisible(),
                    ChatBubbleType = chatBubbleType.file,
                    Message = miniClientData.Instance.client.file_helper.path + @$"\Files\{(string)communication_message.Data[1]}",
                    FileInfoModel = new fileInfoModel((string)communication_message.Data[1], true)
                };
                ChatBubbleModels.Add(info);
            }));
        }
        private void initChatMessageFormDataBase(string uid)
        {
            List<chatBubbleModel> chatBubbles= InfoDao.SelectChatModel(userData.Instance.user.uid, uid);
            foreach(chatBubbleModel chatBubbleModel in chatBubbles)
            {
                ChatBubbleModels.Add(chatBubbleModel);
            }
        }
        private void initChattingOppsite()
        {
            isGroup = userData.Instance.nowChattingWithGroup;
            if (userData.Instance.nowChattingWithGroup)
            {
                UserDataModel = (userDataModel)GroupDao.SelectById(userData.Instance.nowChattingWith);
            }
            else
            {
                UserDataModel = (userDataModel)FriendDao.SelectById(userData.Instance.user.uid, userData.Instance.nowChattingWith);
            }
        }
        private Visibility isTimeVisible()
        {
            if (ChatBubbleModels != null && ChatBubbleModels.Count != 0 && ChatBubbleModels[ChatBubbleModels.Count - 1].SendTime > DateTime.Now.AddMinutes(-5))
            {
                return Visibility.Collapsed;
            }
            return Visibility.Visible;
        }
    }
}
